<template>
  <!-- ContactsMap 人脉地图 -->
  <PageContainer>
    <Header v-model="headerHeight" :is-box-shadow="false" title="人脉地图">
      <template #header>
        <view class="disFlxAC" style="height: inherit">
          <view
            class="w-37 disFlxAC"
            style="height: inherit; justify-content: center"
            @click="handleBack"
          >
            <text v-if="isTabbarPage" class="ali-icon fz-20">{{ '\ue65c' }}</text>
            <text v-else class="ali-icon fz-15">&#xe6aa;</text>
          </view>
          <view class="tabs">
            <template v-for="v in getTabsData" :key="v.type">
              <view
                :class="['tabs-item', params.contactsType === v.type && 'item-active']"
                @click="mainChange(v.type)"
              >
                {{ v.name }}
              </view>
            </template>
          </view>
        </view>
      </template>
    </Header>
    <view
      class="page-container"
      :style="{
        height: containerHeight,
      }"
    >
      <view
        class="container"
        :style="{
          height: containerHeight,
        }"
      >
        <!-- 头部附加筛选功能 -->
        <FilterControl
          ref="filterControlRef"
          :assType="initParams.assType"
          :distance-value="params.distance"
          @filter-change="filterChange"
          @region-change="regionChange"
          @source-type-change="sourceTypeChange"
          @arear-change="handleArearChange"
        />

        <map
          id="contactsMapId"
          style="width: 100%; height: 100%"
          :show-location="true"
          :enable-zoom="true"
          :enable-scroll="true"
          :enable-building="true"
          :min-scale="8"
          :longitude="centerLocation.longitude"
          :latitude="centerLocation.latitude"
          :markers="markersRef"
          :scale="mapScale"
          @labeltap="markertap"
          @markertap="markertap"
          @regionchange="regionchange"
        />

        <!-- 地图回到当前位置 -->
        <view
          :class="['backto-start', isStartLocation && 'active']"
          :style="getBacktoStartStyle"
          @click="backCurrentPosition"
        >
          <text class="ali-icon">&#xe64a;</text>
        </view>

        <!-- 切换列表 -->
        <view
          v-if="membersRef.length"
          :style="getShowListStyle"
          class="show-list"
          @click="switchList('list')"
        >
          <text class="ali-icon">&#xe65c;</text>
          <text>查看列表</text>
        </view>

        <!-- 滑块 -->
        <CardSwiper
          v-model:current="membersSwiperCurrent"
          :show="cardSwiperShow"
          :members="membersRef"
          :tabbar-height="tabbarHeight"
          :contacts-type="params?.contactsType"
          :source-type="params?.assType"
          :show-more-view="membersPage < membersTotalPages"
          @swiper-change="handleSwiperChange"
          @load-more="handleLoadMore"
        />
        <!-- 列表 -->
        <CardList
          :show="cardListShow"
          :members="membersRef"
          :tabbar-height="tabbarHeight"
          :contacts-type="params?.contactsType"
          :source-type="params?.assType"
          :show-more-view="membersPage < membersTotalPages"
          @hide-list="switchList('swiper')"
          @load-more="handleLoadMore"
        />
      </view>
    </view>
  </PageContainer>
</template>

<script lang="ts" setup>
  /**  ContactsMap  人脉地图 */
  import PageContainer from '@/components/PageContainer/index.vue';
  import {
    type ContactsConfigResult,
    type MemberContactsData,
    type MemberContactsVoList,
  } from '@/api/contactsMap/types';
  import { reactive, ref, unref, computed, nextTick, onMounted } from 'vue';
  import Header from '@/components/Header/index.vue';
  import FilterControl from './components/FilterControl.vue';
  import CardSwiper from './components/CardSwiper.vue';
  import CardList from './components/CardList.vue';
  import { ContactsTypeEnum, SourceTypeEnum, ViewTypeEnum } from '@/enums/contactsEnum';
  import { useLocation } from '@/hooks/core/useLocation';
  import { navigateBack, navigateTo } from '@/router';
  import { useAppStoreWithOut } from '@/store/modules/app';
  import { useAuthSetting } from '@/hooks/core/useAuthSetting';
  import { useDebounceFn, useEventBus } from '@vueuse/core';
  import { cloneDeep } from 'lodash-es';
  import {
    defaultScale,
    markerStyle,
    useContactsMap,
    type MarkersRef,
  } from './hooks/useContactsMap';
  import { memberContacts, memberContactsInfoList } from '@/api/contactsMap';
  import { logManager } from '@/utils/log';
  import useComponentSize from './hooks/useComponentStyle';

  import { mapAreaInfoFooKey } from './utils/fooKey';
  import type { FilterControlRef } from './types/refs';
  import type { IAreaDataResultItem } from '@/api/indexTypes';
  import { calculateDistance } from './utils';
  import { onShow } from '@dcloudio/uni-app';
  import { SceneValuesEnum } from '@/enums/sceneValuesEnum';
  import { propTypes } from '@/utils/propTypes';

  wx.hideShareMenu({
    menus: ['shareTimeline'],
  });

  const props = defineProps({
    isTabbarPage: propTypes.bool.def(false),
  });

  const MapIconPerson =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-icon-1.png';
  const MapIconPersonActive =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-icon-1-active.png';
  const mapClusterPerson =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-cluster-icon-1.png';
  const MapIconUnit =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-icon-2.png';
  const MapIconUnitActive =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-icon-2-active.png';
  const mapClusterUnit =
    'https://hb-saas.obs.cn-south-1.myhuaweicloud.com/mall/saas/icon/map/map-cluster-icon-2.png';

  const { getContactsConfig } = useAppStoreWithOut();
  const { getLocation } = useLocation();
  const { authErrorCallbak } = useAuthSetting();
  const bus = useEventBus(mapAreaInfoFooKey);

  const filterControlRef = ref<FilterControlRef | null>(null);

  const headerHeight = ref(0);
  const tabbarHeight = ref('100rpx');

  function handleBack() {
    if (props.isTabbarPage) {
      navigateTo({ name: 'contactList' });
    } else {
      navigateBack();
    }
  }

  const containerHeight = computed(() => {
    if (props.isTabbarPage) {
      return `calc(100vh - ${unref(tabbarHeight)} - env(safe-area-inset-bottom) - ${unref(
        headerHeight,
      )}px)`;
    }
    return `calc(100vh - ${unref(headerHeight)}px)`;
  });

  const initParams: MemberContactsData = {
    mapType: ViewTypeEnum.MAP,
    keyword: '',
    distance: void 0,
    currentLatitude: 0,
    currentLongitude: 0,
    assType: SourceTypeEnum.INSIDE,
    contactsType: ContactsTypeEnum.PERSON,
    typeId: [],
    levelId: [],
    industryId: [],
    provinceId: void 0,
    cityId: void 0,
    areaNewId: void 0,
    scale: defaultScale.start,
    isFirst: true,
  };

  const params = reactive<MemberContactsData>(cloneDeep(unref(initParams)));

  const config = ref<ContactsConfigResult>();
  const getTabsData = computed(() => {
    if (!config.value) return [];
    const { unitListShow, connectionListShow } = config.value;
    const data = [];

    if (!connectionListShow) {
      data.push({ name: '人脉地图', type: ContactsTypeEnum.PERSON });
    } else {
      params.contactsType = ContactsTypeEnum.COMPANY;
    }

    if (!unitListShow) {
      data.push({ name: '单位地图', type: ContactsTypeEnum.COMPANY });
    }

    return data;
  });

  const membersRef = ref<MemberContactsVoList[]>([]);
  const membersSwiperCurrent = ref(0);
  const cardSwiperShow = ref(false);
  const cardListShow = ref(false);
  const { getBacktoStartStyle, getShowListStyle } = useComponentSize(cardSwiperShow);
  const memberMapKey = ref('');

  /**
   * @description 请求地图标点数据
   * @date 09/02/2023
   */
  async function getApiData() {
    try {
      const res = await memberContacts(params as MemberContactsData);
      memberMapKey.value = res.memberMapKey;
      if (res.areaInfoVo) {
        bus.emit(res.areaInfoVo);
      }

      const { memberMapContactsVoList, memberDistrictsListVoList } = res;
      if (memberDistrictsListVoList?.length) {
        /** 绘制统计数据 */
        await createClusterMarkers(
          memberDistrictsListVoList,
          params.contactsType === ContactsTypeEnum.PERSON ? mapClusterPerson : mapClusterUnit,
          params.contactsType === ContactsTypeEnum.PERSON ? '#000' : '#fff',
        );
      } else if (memberMapContactsVoList?.length) {
        /** 绘制标点数据 */
        await createMarkers(memberMapContactsVoList, getMarkerIcon());
      } else {
        markersRef.value = [];
        // await _removeMarkers({ markerIds: markersRef.value.map((item) => item.id) });
      }
      return res;
    } catch (error) {
      console.error(error);
    } finally {
    }
  }

  const debounceRequest = useDebounceFn(getApiData, 500);

  /** 数据主体切换 */
  function mainChange(type: ContactsTypeEnum) {
    console.log('mainChange', type);
    if (params.contactsType === type) return;
    params.contactsType = type;
    debounceRequest();
  }

  /** 获取marker的图标 */
  function getMarkerIcon(isActive?: boolean) {
    const isPerson = params.contactsType === ContactsTypeEnum.PERSON;
    if (isActive) {
      return isPerson ? MapIconPersonActive : MapIconUnitActive;
    }
    return params.contactsType === ContactsTypeEnum.PERSON ? MapIconPerson : MapIconUnit;
  }

  const {
    centerLocation,
    mapScale,
    markersRef,
    moveToLocation,
    includePoints,
    changeMapScale,
    changeMapCenter,
    markertap,
    regionchange,
    createClusterMarkers,
    createMarkers,
    _removeMarkers,
  } = useContactsMap({
    mapId: 'contactsMapId',
    defaultScale: initParams.scale,
    regionchangeAfter: async (e) => {
      if (params.isFirst) return;
      if (e.detail?.scale) {
        const scale = Math.round(e.detail?.scale || 0);
        params.scale = scale;
      }

      if (e.type === 'begin') {
        switchList('auto');
        filterControlRef.value?.reset();
        isStartLocation.value = false;
        return;
      }

      /** 范围模式 拖动地图加载数据 */
      if (e.type === 'end') {
        let latitude: number = 0,
          longitude: number = 0;
        if (e.detail && e.causedBy === 'drag' && e.detail.centerLocation) {
          latitude = e.detail.centerLocation.latitude;
          longitude = e.detail.centerLocation.longitude;
        } else if (e.centerLocation && e.gesture) {
          latitude = e.centerLocation.latitude;
          longitude = e.centerLocation.longitude;
        }

        if (latitude && longitude) {
          const distance = calculateDistance(
            Number(params.latitude),
            Number(params.longitude),
            Number(latitude),
            Number(longitude),
          );
          if (distance < 0.5) {
            focusMarker();
            return;
          }
          params.latitude = latitude;
          params.longitude = longitude;
        }

        await debounceRequest();
      }
    },
    markertapAfter: async (markerId) => {
      isStartLocation.value = false;
      switchList('auto', false);
      const item = markersRef.value.find((item) => item.id === markerId);
      if (!item) throw 'marker 数据不存在';
      const latitude = Number(item.latitude);
      const longitude = Number(item.longitude);
      /** 统计数据 */
      if (item?.scale) {
        filterControlRef.value?.reset();
        params.scale = item.scale;
        params.latitude = latitude;
        params.longitude = longitude;
        await getApiData();
        if (markersRef.value.length) {
          includePoints();
        } else {
          params.scale = defaultScale.area;
          params.latitude = latitude;
          params.longitude = longitude;
          moveToLocation({ latitude, longitude });
        }
        return;
      }

      /** 聚焦当前点击的标点 */
      focusMarker(markerId);

      const index = membersRef.value.findIndex((v) => v.memberLeadingId === markerId);
      if (index !== -1) {
        membersSwiperCurrent.value = index;
        switchList('swiper');
        return;
      }
      membersPage.value = 1;
      params.latitude = latitude;
      params.longitude = longitude;
      handleLoadMore();
    },
    // markerClusterClickAfter: (e) => {
    //   isStartLocation.value = false;
    //   if (unref(isFocusMarkerId)) {
    //     markersRef.value.forEach((v, i) => {
    //       v.width = markerStyle.width;
    //       v.height = markerStyle.height;
    //       v.iconPath = getMarkerIcon();
    //     });
    //   }

    //   switchList('auto');
    // },
  });

  const focusMarkerId = ref<number>();
  /**
   * @description 使marker聚焦
   * @date 11/02/2023
   * @param {number} markerId
   */
  async function focusMarker(markerId?: number) {
    return new Promise(async (resolve, reject) => {
      console.log('focusMarker', markerId);
      focusMarkerId.value = void 0;
      if (unref(markersRef).length === 0 || unref(markersRef)[0]?.scale) return;
      let item = null;
      let index = -1;
      markersRef.value.forEach((v, i) => {
        v.width = markerStyle.width;
        v.height = markerStyle.height;
        v.iconPath = getMarkerIcon();
        if (v.id === markerId) {
          item = v;
          index = i;
        }
      });
      if (!item || index == -1) return resolve(true);
      markersRef.value.splice(index, 1);
      item = cloneDeep(item) as MarkersRef;
      await _removeMarkers({
        markerIds: [item.id],
      });
      item.width = markerStyle.width * 2;
      item.height = markerStyle.height * 2;
      item.iconPath = getMarkerIcon(true);
      focusMarkerId.value = markerId;
      markersRef.value.push(item);
      await moveToLocation({ latitude: item.latitude, longitude: item.longitude });
      return resolve(true);
    });
  }

  const isStartLocation = ref(true);

  /** 回到当前位置 */
  async function backCurrentPosition() {
    console.log('backCurrentPosition');
    if (isStartLocation.value) return;
    switchList('auto');
    filterControlRef.value?.reset();
    isStartLocation.value = true;
    try {
      const { currentLatitude, currentLongitude } = params;
      params.latitude = currentLatitude;
      params.longitude = currentLongitude;
      changeMapCenter({
        latitude: currentLatitude as number,
        longitude: currentLongitude as number,
      });
      nextTick(async () => {
        moveToLocation({ latitude: currentLatitude, longitude: currentLongitude });
        changeMapScale(initParams.scale as number);
        resetParams();
        await getApiData();
        console.log('BacktoStart Success');
      });
    } catch (error) {
      authErrorCallbak('userLocation', { errno: 103, errMsg: 'fail auth deny' });
      isStartLocation.value = false;
    }
  }

  /** 切换名片显示方式 */
  function switchList(type: 'swiper' | 'list' | 'auto', isClear: boolean = true) {
    console.log('switchList', type);
    if (membersRef.value.length === 0) return;
    switch (type) {
      case 'swiper':
        cardListShow.value = false;
        cardSwiperShow.value = true;
        break;
      case 'list':
        cardListShow.value = true;
        cardSwiperShow.value = false;
        break;

      default:
        cardListShow.value = false;
        cardSwiperShow.value = false;
        if (isClear) {
          membersRef.value = [];
          membersPage.value = 1;
          membersTotalPages.value = 0;
        }
        break;
    }
  }

  function resetParams() {
    const p = initParams;
    // params.assType = p.assType;
    params.areaNewId = p.areaNewId;
    params.provinceId = p.provinceId;
    params.cityId = p.cityId;
    params.distance = p.distance;
    params.industryId = p.industryId;
    params.levelId = p.levelId;
    params.typeId = p.typeId;
    params.keyword = p.keyword;
    params.scale = p.scale;
  }

  /** 切换数据来源 */
  async function sourceTypeChange(val: SourceTypeEnum) {
    console.log('sourceTypeChange');
    switchList('auto');
    if (val !== SourceTypeEnum.INSIDE) {
      params.industryId = [];
      params.levelId = [];
      params.typeId = [];
    }
    params.assType = val;
    await getApiData();
  }

  /** 省市 切换 */
  async function regionChange(e: {
    provinceItem: IAreaDataResultItem;
    cityItem: IAreaDataResultItem;
  }) {
    console.log('regionChange');
    switchList('auto');
    filterControlRef.value?.reset();
    isStartLocation.value = false;
    params.scale = defaultScale.city;
    params.latitude = Number(e.cityItem.latitude);
    params.longitude = Number(e.cityItem.longitude);
    changeMapCenter({
      latitude: params.latitude,
      longitude: params.longitude,
    });
    await getApiData();
    includePoints();
  }

  /** 用户修改区 */
  async function handleArearChange(val?: IAreaDataResultItem) {
    console.log('handleArearChange', val);
    switchList('auto');
    isStartLocation.value = false;
    if (val) {
      params.scale = defaultScale.maxCity;
      params.latitude = Number(val.latitude);
      params.longitude = Number(val.longitude);
      setTimeout(async () => {
        await moveToLocation({
          latitude: params.latitude,
          longitude: params.longitude,
        });
      }, 300);
      changeMapScale(params.scale);
      await getApiData();
    } else {
      params.scale = defaultScale.city;
      await getApiData();
      includePoints();
    }
  }

  /** 用户修改筛选条件*/
  async function filterChange(val: Recordable<(number | string)[]> | null) {
    console.log('filterChange', val);
    switchList('auto');
    isStartLocation.value = false;
    if (val) {
      params.industryId = (val['industryId'] as number[]) || [];
      params.levelId = (val['memberLevel'] as number[]) || [];
      params.typeId = (val['typeId'] as number[]) || [];
    } else {
      params.areaNewId = void 0;
      params.distance = initParams.distance;
    }
    await getApiData();
  }

  /** 滑块切换 */
  function handleSwiperChange(current: number) {
    console.log('handleSwiperChange', membersRef.value[current].memberLeadingId);
    focusMarker(membersRef.value[current].memberLeadingId);
  }

  const membersPage = ref(1);
  const membersTotalPages = ref(0);
  /** 滑块和列表数据加载更多 */
  async function handleLoadMore() {
    console.log('handleLoadMore');
    switchList('auto', false);
    membersSwiperCurrent.value = 0;
    const res = await memberContactsInfoList({
      ...params,
      current: membersPage.value,
      size: 20,
      memberMapKey: memberMapKey.value,
    });
    membersPage.value++;
    membersTotalPages.value = res.pages;
    membersRef.value = res.records;
    switchList('swiper');
  }

  const isLoading = ref(false);
  /** 初始化 */
  async function __init() {
    isLoading.value = true;
    try {
      // uni.showLoading({ title: '初始化中...' });
      const { latitude, longitude } = await getLocation();
      const cres = await getContactsConfig();
      if (!cres?.unitListShow && cres?.connectionListShow) {
        initParams.contactsType = ContactsTypeEnum.COMPANY;
        params.contactsType = ContactsTypeEnum.COMPANY;
      }
      config.value = cres;
      params.currentLatitude = latitude;
      params.currentLongitude = longitude;
      params.latitude = latitude;
      params.longitude = longitude;
      const res = await getApiData();
      changeMapCenter({ latitude, longitude });
      params.isFirst = false;
      if (res) {
        if (res.memberMapContactsVoList?.length) {
          nextTick(() => {
            markertap({ detail: { markerId: res.memberMapContactsVoList![0].memberLeadingId } });
          });
        }
        if (res.memberMapContactsVoList?.length === 0) {
          includePoints();
        }
      }
    } catch (error) {
      console.log(error);
      logManager.error(error);
      authErrorCallbak('userLocation', { errno: 103, errMsg: `${error}` });
    } finally {
      // uni.hideLoading();
      isLoading.value = false;
    }
  }

  function onReady() {
    if (params.isFirst && !isLoading.value) __init();
  }

  onMounted(onReady);

  onShow(onReady);
</script>

<style lang="scss" scoped>
  .tabs {
    display: flex;
    align-items: center;
    height: 100%;

    .tabs-item {
      position: relative;
      font-weight: 400;
      transition: all 0.3s;
      white-space: nowrap;
      font-size: 28rpx;
      color: #999996;
      padding: 0 16rpx;
      &::before {
        content: '';
        width: 40%;
        height: 4rpx;
        position: absolute;
        left: 30%;
        bottom: -8rpx;
        background-color: #2878ff;
        transform: scale(0);
        transition: all 0.3s;
      }
      &.item-active {
        font-weight: bolder;
        font-size: 28rpx;
        color: #333;
        &::before {
          transform: scale(1);
        }
      }
    }
  }
  .page-container {
    background-color: #fff;
    width: 100vw;
    position: fixed;
    z-index: 999;
    overflow: hidden;
  }
  .container {
    position: relative;
    width: 100vw;

    .backto-start {
      position: absolute;
      background-color: #fff;
      width: 86rpx;
      height: 86rpx;
      border-radius: 20rpx;
      color: #333;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s;
      &.active {
        background-color: #2878ff;
        color: #fff;
      }

      .ali-icon {
        font-size: 50rpx;
      }
    }

    .show-list {
      position: absolute;
      width: 206rpx;
      height: 72rpx;
      background: #ffffff;
      border-radius: 20rpx;
      text-align: center;
      line-height: 72rpx;
      font-size: 28rpx;
      color: #333;
      transition: all 0.3s;
      .ali-icon {
        margin-right: 6rpx;
        font-size: 36rpx;
      }
    }
  }
</style>
